package controlador;

import java.awt.Color;
import java.awt.Font;
import java.util.ArrayList;
import java.util.Iterator;

import vista.VistaAeroNaveFactory;

import vista.VistaAeronave;
import vista.VistaAvionesRestantes;
import vista.VistaEscenario;
import vista.VistaPista;
import vista.VistaPistaFactory;
import vista.VentanaPrincipal;

import modelo.AeroNave;

import modelo.AvionesRestantes;
import modelo.Escenario;
import modelo.Nivel;
import modelo.Pista;

/*import ar.uba.fi.algo3.ejemplos.pelotas.modelo.Mesa;
 import ar.uba.fi.algo3.ejemplos.pelotas.modelo.Pelota;
 import ar.uba.fi.algo3.ejemplos.pelotas.vista.VistaMesa;
 import ar.uba.fi.algo3.ejemplos.pelotas.vista.VistaPelota;
 import ar.uba.fi.algo3.ejemplos.pelotas.vista.VistaPelota2;*/
import ar.uba.fi.algo3.titiritero.ControladorJuego;
import ar.uba.fi.algo3.titiritero.ObjetoVivo;

import ar.uba.fi.algo3.titiritero.SuperficieDeDibujo;
import ar.uba.fi.algo3.titiritero.vista.ObjetoDeTexto;
import ar.uba.fi.algo3.titiritero.vista.Punto;
import ar.uba.fi.algo3.titiritero.vista.TextoEstatico;

public class Juego implements ObjetoVivo {

	private ControladorJuego controlador = null;
	private Nivel nivel;
	private VistaAeroNaveFactory fabricaVistasNaves;
	private VistaPistaFactory fabricaVistasPistas;
	private Escenario escenario;

	public Juego(SuperficieDeDibujo superficieDeDibujo, Nivel nivel) {
		this.escenario = Escenario.getInstance();
		this.fabricaVistasNaves = new VistaAeroNaveFactory();
		this.fabricaVistasPistas = new VistaPistaFactory();
		this.controlador = new ControladorJuego(true);

		VentanaPrincipal ventana = new VentanaPrincipal(controlador);

		this.controlador.setSuperficieDeDibujo(ventana.getSuperficieDeDibujo());
		ventana.setVisible(true);
		VistaEscenario vistaEscenario = new VistaEscenario();
		vistaEscenario.setPosicionable(escenario);

		this.nivel = nivel;

		/*
		 * Instancio los objetos del framework: una ventana y el controlador
		 */

		controlador.agregarObjetoVivo(escenario);
		controlador.agregarObjetoVivo(this);

		/*
		 * Agrego los objetos que actuan como vista a la lista de dibujables del
		 * controlador para que sean repintados al final de cada gameloop
		 */

		controlador.agregarDibujable(vistaEscenario);
		controlador.agregarMouseClickObservador(vistaEscenario);
		controlador.agregarKeyPressObservador(vistaEscenario);

		// Es importante que las pistas se dibujen luego del escenario, porque
		// sino quedan atras
		Iterator<Pista> iter = this.nivel.getIteradorPistas();
		while (iter.hasNext()) {
			Pista pista = iter.next();
			VistaPista vista = fabricaVistasPistas.getVista(pista);
			vista.setPosicionable(pista);
			escenario.agregarEstatico(pista);
			controlador.agregarDibujable(vista);
		}
		iter = null;
		Iterator<AeroNave> iterNaves = escenario.getIteratorNaves();

		// Creo las vistas correspondientes a las naves que ya estan en en
		// modelo
		while (iterNaves.hasNext()) {
			AeroNave nave = iterNaves.next();
			VistaAeronave nuevaVista = fabricaVistasNaves.getVista(nave);
			nuevaVista.setPosicionable(nave);
			controlador.agregarDibujable(nuevaVista);
			controlador.agregarObjetoVivo(nave);
			controlador.agregarObjetoVivo(nuevaVista);
		}

		ObjetoDeTexto avionesRestantes = new AvionesRestantes(nivel);
		VistaAvionesRestantes vistaRestantes = new VistaAvionesRestantes(
				avionesRestantes, Color.cyan, Font.getFont(Font.SERIF));
		controlador.agregarDibujable(vistaRestantes);

		/*
		 * finalmente establezco el intervalo de sleep dentro del gameloop y
		 * comienzo a ejecutar
		 */
		controlador.setIntervaloSimulacion(50);
	}

	public void comenzar() {
		controlador.comenzarJuegoAsyn();
	}

	public void detener() {
		controlador.detenerJuego();
	}

	public void agregarObservadorDeChoques(ObservadorDeChoques observador) {
		this.observadores.add(observador);
	}

	private ArrayList<ObservadorDeChoques> observadores = new ArrayList<ObservadorDeChoques>();

	@Override
	public void vivir() {

		if (escenario.hayColision()) {
			Iterator<ObservadorDeChoques> it = this.observadores.iterator();
			while (it.hasNext()) {
				ObservadorDeChoques obs = it.next();
				obs.huboChoques();
			}
			gameOver();
		}

		AeroNave nuevaNave = this.nivel.getNave();
		if (nuevaNave != null) { // Agregamos nave nueva
			Escenario.getInstance().agregarMovil(nuevaNave);
			VistaAeronave nuevaVista = this.fabricaVistasNaves
					.getVista(nuevaNave);
			nuevaVista.setPosicionable(nuevaNave);
			this.controlador.agregarDibujable(nuevaVista);
			this.controlador.agregarObjetoVivo(nuevaVista);
			this.controlador.agregarObjetoVivo(nuevaNave);
		}

		if ((escenario.getNavesVolando() + nivel.navesRestantes()) == 0)
			ganaste();

	}

	public void gameOver() {
		Font fuente = new Font("Serif", Font.BOLD, 60);
		TextoEstatico textoGO = new TextoEstatico("ALPISTE!", Color.RED, fuente);
		textoGO.setPosicionable(new Punto(250, 100));
		this.controlador.agregarDibujable(textoGO);
	}

	public void ganaste() {
		Font fuente = new Font("Serif", Font.BOLD, 60);
		TextoEstatico textoGA = new TextoEstatico("Nivel finalizado",
				Color.GREEN, fuente);
		textoGA.setPosicionable(new Punto(160, 100));
		this.controlador.agregarDibujable(textoGA);

	}

	public Nivel getNivel() {
		return this.nivel;
	}
}
